import io
import tkinter as tk
import tkinter.simpledialog as tks
import sys


class ControlPad(tk.Frame, io.TextIOBase):
    def __init__(self, parent, height=5, redirection=False):
        """
        模仿命令行的部件。
        创建对象时会自动更改输出流和输入流。
        默认情况下，鼠标移出控件后会将高度缩减为1。通过双击右键可以固定大小。
        :param parent:
        :param height: 部件的高度。
        """
        super().__init__(parent)
        self.parent = parent
        self.text = tk.Text(self, height=height, state='disabled', font=('宋体', 12))
        self.inputbuffer = ''
        self.ininputloop = False
        self.height = height
        self.focus_size = True  # 是否保持控件大小固定。可以通过右键双击更改。
        self.text.bind("<KeyPress>", self._keypress)
        self.text.bind("<Leave>", self._focusout)
        self.text.bind("<Enter>", self._focusin)
        self.text.bind("<Double-Button-3>", self._double3)
        self.text.pack(side='right', fill='x', expand=1)

        if redirection:
            sys.stdout = self
            sys.stdin = self
            sys.stderr = self

    def show(self):
        self.text['height'] = self.height

    def write(self, __s: str) -> int:
        self.text['state'] = 'normal'
        self.text['height'] = self.height
        self.text.insert("end", __s)
        self.text.see("end")
        self.text['state'] = 'disabled'
        return len(__s)

    def readline(self, __size: int = ...) -> str:
        self.text['state'] = 'normal'
        self.ininputloop = True
        while self.ininputloop:
            self.parent.update()
        self.text['state'] = 'disabled'
        __str = self.inputbuffer
        self.inputbuffer = ""
        return __str

    def _keypress(self, e):
        if self.text.index('insert') != self.text.index('end-1c'):
            return "break"
        if e.char == '\r':
            self.ininputloop = False
        else:
            self.inputbuffer += e.char

    def _focusout(self, e):
        if not self.focus_size:
            self.text['height'] = 1

    def _focusin(self, e):
        self.text['height'] = self.height

    def _double3(self, e):
        self.focus_size = not self.focus_size


class UnionView(tk.Text):
    def __init__(self, parent, *args, **kwargs):
        """
        在一个区域显示多个部件。

        root = tk.Tk()
        wv = UnionView(root)
        btn = tk.Button(root, text="Click me!", command=clicked)
        btn1 = tk.Button(wv, text="1")
        btn2 = tk.Button(wv, text="2")
        btn3 = tk.Button(wv, text="3")
        wv.add(btn1, name="0").add(btn2, name="1").add(btn3, name="2")
        btn.pack()
        wv.pack()
        root.mainloop()

        :param parent:
        :param args:
        :param kwargs:
        """
        super().__init__(parent, *args, **kwargs)
        self.widgets = list()
        self.now_ = None
        self.name2id = dict()

    def add(self, widget, name=None):
        if name is not None:
            assert name not in self.name2id
            self.name2id[name] = len(self.widgets)
        self.widgets.append(widget)
        return self

    def show(self, id_or_name):
        if not isinstance(id_or_name, int):
            idx = self.name2id[id_or_name]
        else:
            idx = id_or_name
        if self.now_ is not None:
            self.widgets[self.now_].pack_forget()
        self.widgets[idx].pack(side="right", fill="both")
        self.now_ = idx

    def widget(self):
        if self.now_ is None:
            return None
        return self.widgets[self.now_]

    def __len__(self):
        return len(self.widgets)


class BionicText(tk.Text):
    def __init__(self, parent, scrolling=True, *args, **kwargs):
        """
        以bionic样式显示英文文本。
        + show(text)
            显示文本。
        + clear()
            清除文本。
        :param parent:
        :param scrolling:
        :param args:
        :param kwargs:
        """
        super().__init__(parent, *args, **kwargs)
        if scrolling:
            self.scrollbal = tk.Scrollbar()
            self.scrollbal.pack(side='right', fill='y')
            self.pack(side='right', fill='both')
            self.scrollbal['command'] = self.yview
            self['yscrollcommand'] = self.scrollbal.set
        self.showing = False

    def show(self, text):
        font_name, font_size = self['font'].split(" ")
        self.tag_config("bold", font=(font_name, font_size, "bold"))
        for verb in text.split(" "):
            len_verb = len(verb)
            if len_verb > 5:
                self.insert(tk.END, verb[:int(len_verb / 2)], "bold")
                self.insert(tk.END, verb[int(len_verb / 2):])
            else:
                self.insert(tk.END, verb)
            self.insert(tk.END, " ")
            self.showing = True

    def clear(self):
        self.delete(1.0, tk.END)
        self.showing = False


if __name__ == '__main__':
    root = tk.Tk()
    pad = ControlPad(root)
    # botton = tk.Button()
    # botton.bind("<ButtonRelease-1>", lambda e: print(input("你的名字是什么？")))
    print(pad.__init__.__doc__)
    pad.pack(side='bottom', fill='x')
    # botton.pack()
    root.mainloop()
